package com.lframework.xingyun.basedata.mappers;

import com.lframework.starter.web.core.mapper.BaseMapper;
import com.lframework.xingyun.basedata.bo.product.info.ProductInfoBo;
import com.lframework.xingyun.basedata.dto.product.ProductSelectorDto;
import com.lframework.xingyun.basedata.dto.product.ProductSpecDto;
import com.lframework.xingyun.basedata.entity.*;
import com.lframework.xingyun.basedata.vo.product.info.QueryProductSelectorVo;
import com.lframework.xingyun.basedata.vo.product.info.QueryProductVo;
import com.lframework.starter.web.core.annotations.permission.DataPermission;
import com.lframework.starter.web.core.annotations.permission.DataPermissions;
import com.lframework.starter.web.core.annotations.sort.Sort;
import com.lframework.starter.web.core.annotations.sort.Sorts;
import com.lframework.starter.web.inner.components.permission.ProductDataPermissionDataPermissionType;
import java.util.List;
import org.apache.ibatis.annotations.Param;

/**
 * <p>
 * Mapper 接口
 * </p>
 *
 * @author zmj
 * @since 2021-07-11
 */
public interface ProductMapper extends BaseMapper<Product> {

    /**
     * 查询列表
     *
     * @param vo
     * @return
     */
    @DataPermissions(type = ProductDataPermissionDataPermissionType.class, value = {
            @DataPermission(template = "product", alias = "g"),
            @DataPermission(template = "brand", alias = "b"),
            @DataPermission(template = "category", alias = "c")
    })
    @Sorts({
            @Sort(value = "code", alias = "g", autoParse = true),
            @Sort(value = "name", alias = "g", autoParse = true),
            @Sort(value = "createTime", alias = "g", autoParse = true),
            @Sort(value = "updateTime", alias = "g", autoParse = true),
    })
    List<Product> query(@Param("vo") QueryProductVo vo);

    /**
     * 查询商品品种数
     *
     * @param vo
     * @return
     */
    Integer queryCount(@Param("vo") QueryProductVo vo);

    /**
     * 选择器
     *
     * @param vo
     * @return
     */
    @DataPermissions(type = ProductDataPermissionDataPermissionType.class, value = {
            @DataPermission(template = "product", alias = "g"),
            @DataPermission(template = "brand", alias = "b"),
            @DataPermission(template = "category", alias = "c")
    })
    List<ProductSelectorDto> selector(@Param("vo") QueryProductSelectorVo vo);

    /**
     * 根据ID查询
     *
     * @param id
     * @return
     */
    Product findById(String id);

    /**
     * 根据ID查询选择器DTO
     *
     * @param productIds
     * @return
     */
    List<ProductSelectorDto> findSelectorDtoByIds(@Param("productIds") List<String> productIds);

    /**
     * 查询没有属性的ID
     *
     * @param propertyId
     * @return
     */
    List<String> getIdNotInProductProperty(String propertyId);

    /**
     * 根据分类ID查询
     *
     * @param categoryId
     * @return
     */
    List<String> getIdByCategoryId(String categoryId);

    /**
     * 根据分类ID查询
     *
     * @param categoryIds
     * @return
     */
    List<Product> getByCategoryIds(@Param("categoryIds") List<String> categoryIds,
                                   @Param("productType") Integer productType);

    /**
     * 根据品牌ID查询
     *
     * @param brandIds
     * @return
     */
    List<Product> getByBrandIds(@Param("brandIds") List<String> brandIds,
                                @Param("productType") Integer productType);

    /**
     * 根据商品ID查询单位
     * @param productId
     * @return
     */
    List<Unit> getUnitByProductId(@Param("productId") String productId);

    default List<ProductInfoBo> selectByBo(List<String> productIds) {
        return defaultJoinWrapper()
                .selectAs(Product::getId, ProductInfoBo::getProductId)
                .selectAs(Product::getProductType, ProductInfoBo::getProductType)
                .selectAs(ProductCategory::getId, ProductInfoBo::getProductCategoryId)
                .selectAs(ProductCategory::getName, ProductInfoBo::getCategoryName)
                .selectAs(ProductBrand::getId, ProductInfoBo::getProductBrandId)
                .selectAs(ProductBrand::getName, ProductInfoBo::getBrandName)
                .selectAs(Product::getName, ProductInfoBo::getProductName)
                .selectAs(Product::getCode, ProductInfoBo::getProductCode)
                .selectAs(Product::getSkuCode, ProductInfoBo::getSkuCode)
                .selectAs(Product::getExternalCode, ProductInfoBo::getExternalCode)
                .selectAs(Product::getUnit, ProductInfoBo::getUnit)
                .selectAs(Product::getSpec, ProductInfoBo::getSpec)
                .selectAs(ProductRetail::getPrice, ProductInfoBo::getSalePrice)
                .leftJoin(ProductCategory.class, ProductCategory::getId, Product::getCategoryId)
                .leftJoin(ProductBrand.class, ProductBrand::getId, Product::getBrandId)
                .leftJoin(ProductRetail.class, ProductRetail::getId, Product::getId)
                .in(Product::getId, productIds)
                .list(ProductInfoBo.class);
    }

    /**
     * 根据商品编码查询商品规格
     * @param code
     * @return
     */
    default List<Product> selectSpecProductByCode(String code) {
        return defaultJoinWrapper()
                .selectAll(Product.class)
                .eq(Product::getCode, code)
                .list(Product.class);
    }

    /**
     * 根据商品ID查询商品规格
     * @param productId 商品ID
     * @return 商品规格列表
     */
    default List<ProductSpecDto> selectSpecProductDtoByMainProductId(String productId) {
        return defaultJoinWrapper()
                .selectAs(Product::getId, ProductSpecDto::getSpecId)
                .selectAs(Product::getSpec, ProductSpecDto::getSpec)
                .selectAs(Product::getSkuCode, ProductSpecDto::getSkuCode)
                .selectAs(Product::getUnit, ProductSpecDto::getUnit)
                .selectAs(Product::getStockUnit, ProductSpecDto::getStockUnit)
                .selectAs(ProductPurchase::getPrice, ProductSpecDto::getPurchasePrice)
                .selectAs(Product::getRetailUnit, ProductSpecDto::getRetailUnit)
                .selectAs(ProductRetail::getPrice, ProductSpecDto::getRetailPrice)
                .selectAs(Product::getSalesUnit, ProductSpecDto::getSalesUnit)
                .selectAs(ProductSale::getPrice, ProductSpecDto::getSalePrice)
                .selectAs(Product::getWeight, ProductSpecDto::getWeight)
                .selectAs(Product::getVolume, ProductSpecDto::getVolume)
                .selectAs(Product::getAvailable, ProductSpecDto::getAvailable)
                .selectAs(Product::getValidPropertyValues, ProductSpecDto::getValidPropertyValues)
                .selectCollection(ProductPropertyRelation.class, ProductSpecDto::getProperty, map ->
                    map.result(ProductPropertyRelation::getPropertyId, ProductSpecDto.PropertyDto::getPropertyId)
                        .result(ProductPropertyRelation::getPropertyItemId, ProductSpecDto.PropertyDto::getPropertyItemId)
                )
                .leftJoin(ProductPurchase.class, ProductPurchase::getId, Product::getId)
                .leftJoin(ProductSale.class, ProductSale::getId, Product::getId)
                .leftJoin(ProductRetail.class, ProductRetail::getId, Product::getId)
                .leftJoin(ProductPropertyRelation.class, ProductPropertyRelation::getProductId, Product::getId)
                .eq(Product::getMainProductId, productId)
                .list(ProductSpecDto.class);
    }
}
